1.The COVID-19 data is from John Hopkins University, https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_time_series.
2.The Australia map data if from GADM, https://gadm.org/data.html
3.The country code is from plotly dataset, https://github.com/plotly/datasets/blob/master/2014_world_gdp_with_codes.csv
---
title: "Coronavirus Disease (COVID-19) Dashboard"
author: Jiaying Wu
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
source_code: embed
theme: cerulean
social: [ "twitter", "facebook", "menu" ]
---
```{r setup, include=FALSE}
library(flexdashboard)
library(tidyverse)
library(lubridate)
library(plotly)
library(ggthemes)
library(knitr)
library(DT)
library(rmapshaper)
library(sugarbag)
library(gganimate)
library(brotools)
```
World
=======================================================================
```{r time_series}
# time series of confirmed cases in each area
ts_confirmed <- read_csv(
file = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv",
col_types = cols(
.default = col_double(),
`Province/State` = col_character(),
`Country/Region` = col_character()
)) %>%
pivot_longer(cols = -c(`Province/State`, `Country/Region`, Lat, Long), names_to = "Date", values_to = "Confirmed") %>%
mutate(Date = mdy(Date))
# time series of recovered cases in each area
ts_recovered <- read_csv(
file = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv",
col_types = cols(
.default = col_double(),
`Province/State` = col_character(),
`Country/Region` = col_character()
)) %>%
pivot_longer(cols = -c(`Province/State`, `Country/Region`, Lat, Long), names_to = "Date", values_to = "Recovered") %>%
mutate(Date = mdy(Date))
# time series of deaths cases in each area
ts_deaths <- read_csv(
file = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv",
col_types = cols(
.default = col_double(),
`Province/State` = col_character(),
`Country/Region` = col_character()
)) %>%
pivot_longer(cols = -c(`Province/State`, `Country/Region`, Lat, Long), names_to = "Date", values_to = "Deaths") %>%
mutate(Date = mdy(Date))
# time series of 3 cases in each area
ts_all <- ts_confirmed %>%
left_join(ts_recovered) %>%
mutate(Recovered = replace_na(Recovered, replace = 0)) %>%
left_join(ts_deaths) %>%
mutate(Deaths = replace_na(Deaths, replace = 0))
# recent case by region
region_recent <- ts_all %>%
group_by(`Country/Region`, Date) %>%
summarise(Confirmed = sum(Confirmed),
Recovered = sum(Recovered),
Deaths = sum(Deaths)) %>%
mutate('New Case' = Confirmed - lag(Confirmed, 1)) %>%
filter(Date == max(Date))
recent_day <- max(region_recent$Date)
```
Column {data-width=400 .bg-secondary}
-----------------------------------------------------------------------
```{r total_summary_cases}
# aggregate in date level
ts_all_date <- ts_all %>%
rename(Region = `Country/Region`) %>%
group_by(Date) %>%
summarise(Confirmed = sum(Confirmed),
Deaths = sum(Deaths),
Recovered = sum(Recovered)) %>%
mutate('New Case' = Confirmed - lag(Confirmed, 1))
ts_recent <- ts_all_date %>%
filter(Date == max(Date))
```
```{r country_code}
# get country code
code <- read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv',
col_types = cols(
COUNTRY = col_character(),
`GDP (BILLIONS)` = col_double(),
CODE = col_character()
)) %>%
select(COUNTRY, CODE) %>%
rename(Region = COUNTRY,
Code = CODE) %>%
rownames_to_column("id")
code$id <- as.integer(code$id)
```
```{r replace_region_name}
# Rename the unmatched region name in code
code$Region <- code$Region %>%
str_replace(pattern = "United States", replacement = "US") %>%
str_replace(pattern = "Macedonia", replacement = "North Macedonia") %>%
str_replace(pattern = "Czech Republic", replacement = "Czechia") %>%
str_replace(pattern = "Taiwan", replacement = "Taiwan*") %>%
str_replace(pattern = "West Bank", replacement = "West Bank and Gaza") %>%
str_replace(pattern = "Congo, Democratic Republic of the", replacement = "Congo (Kinshasa)") %>%
str_replace(pattern = "Congo, Republic of the", replacement = "Congo (Brazzaville)") %>%
str_replace(pattern = "Bahamas, The", replacement = "Bahamas") %>%
str_replace(pattern = "Swaziland", replacement = "Eswatini") %>%
str_replace(pattern = "Gambia, The", replacement = "Gambia")
#str_replace(pattern = "", replacement = "Holy See") %>%
#str_replace(pattern = "", replacement = "Western Sahara")
```
```{r recent_case_cumulative}
# recent cumulative case and join daily case summary with code name
# remove Diamond Princess and MS Zaandam, they are boat, not region
region_recent_code <- region_recent %>%
filter(`Country/Region` != "Diamond Princess") %>%
filter(`Country/Region` != "MS Zaandam") %>%
left_join(code, by = c("Country/Region" = "Region")) %>%
arrange(desc(Confirmed))
```
### `r paste0("Confirmed Cases at ", ts_recent$Date)`
```{r total_confirmed}
valueBox(prettyNum(ts_recent$Confirmed, big.mark = ","), icon = "fa-users", color = "#C70039")
```
### `r paste0("New Cases at ", ts_recent$Date)`
```{r world_new}
valueBox(prettyNum(ts_recent$`New Case`, big.mark = ","), icon = "fa-users", color = "#fc6b03")
```
### `r paste0("Recovered Cases at ", ts_recent$Date)`
```{r total_recovered}
valueBox(prettyNum(ts_recent$Recovered, big.mark = ","), icon = "ion-checkmark-circled", color = '#3FBF7F')
```
### `r paste0("Deaths Cases at ", ts_recent$Date)`
```{r total_deaths}
valueBox(prettyNum(ts_recent$Deaths, big.mark = ","), icon = "ion-close-circled", color = '#d3d3d3')
```
```{r first_case_day}
case_nz <- ts_all %>% filter(Confirmed>0)
first_case_day <- min(case_nz$Date)
```
### `r paste0("Days since First Confirmed Case at ", first_case_day)`
```{r pass_day}
current <- Sys.Date()
pass_day <- current - first_case_day
valueBox(prettyNum(pass_day, big.mark = ","), icon = "ion-android-time", color = '#FFC300')
```
Column {data-width=600 .tabset}
-----------------------------------------------------------------------
### World COVID-19 Confirmed Cases by Region
```{r set_map}
#Set country boundaries as light grey
line <- list(color = toRGB("#d1d1d1"), width = 0.2)
#Specify map projection and options
geo <- list(
showframe = FALSE,
showcoastlines = FALSE,
projection = list(type = 'orthographic'),
resolution = '100',
showcountries = TRUE,
countrycolor = '#d1d1d1',
showocean = TRUE,
oceancolor = '#064273',
showlakes = TRUE,
lakecolor = '#99c0db',
showrivers = TRUE,
rivercolor = '#99c0db',
bgcolor = '#e8f7fc')
```
```{r confirm_map_3d}
confirm_map_3d <- plot_geo() %>%
layout(geo = geo,
paper_bgcolor = '#e8f7fc',
title = paste0("World COVID-19 Confirmed Cases by Region at ", recent_day)) %>%
add_trace(data = region_recent_code,
z = ~Confirmed,
color = ~Confirmed,
colors = 'Reds',
text = ~`Country/Region`,
locations = ~Code,
marker = list(line = line))
confirm_map_3d
```
### Search by Region
```{r table_case}
region_recent_code %>%
select(`Country/Region`,Code, Date, Confirmed, `New Case`, Recovered, Deaths) %>%
arrange(desc(Confirmed)) %>%
datatable(
rownames = FALSE,
fillContainer = TRUE,
options = list(
bPaginate = FALSE)
)
```
Daily
=======================================================================
Column {data-width=500}
-----------------------------------------------------------------------
### World COVID-19 Cumulative Cases by Day
```{r barchart_cum}
ts_date_long <- ts_all_date %>%
select(-c(Confirmed, `New Case`)) %>%
pivot_longer(cols = -Date, names_to = "Status", values_to = "Cases")
barchart <- ggplot(data = ts_all_date, aes(x = Date)) +
geom_bar(aes(y = Confirmed), position = "stack", stat = "identity", fill = "#ff5050") +
geom_bar(data = ts_date_long, aes(y = Cases, fill = Status), position = "stack", stat = "identity") +
scale_fill_manual(values = c("#000000", "#009900")) +
scale_y_continuous(labels = scales::label_number_si(accuracy = 0.1)) +
theme_solarized(base_size = 10, light = TRUE)+
theme(plot.margin = margin(0, 0, 0, 0, "pt"),
panel.background = element_rect(fill = "White"),
legend.position = "bottom",
axis.title = element_blank(),
#axis.text.y = element_blank(),
axis.ticks = element_blank()) +
ggtitle("World COVID-19 Cumulative Cases by Day")
ggplotly(barchart) %>%
layout(legend = list(orientation = 'h'))
```
Column {data-width=500}
-----------------------------------------------------------------------
### Animation of World COVID-19 Case Increment by Day
```{r ts_increment}
ts_increment_long <- ts_all_date %>%
select(-`New Case`) %>%
mutate(Confirmed = Confirmed - lag(Confirmed,1),
Deaths = Deaths - lag(Deaths,1),
Recovered = Recovered - lag(Recovered,1)) %>%
filter(Date != min(Date)) %>%
pivot_longer(-Date, names_to = "Case", values_to = "Increment")
```
```{r animate_world_increment}
animate_world_increment <-
ggplot(data = ts_increment_long,
mapping = aes(x = Date, y = Increment, group = Case, color = Case)) +
geom_line() +
scale_color_brewer(palette = "Set3") +
geom_segment(aes(xend = max(Date)+1, yend = Increment), linetype = 2, colour = 'grey') +
geom_text(aes(x = max(Date)+1, label = Case), hjust = 0) +
theme_blog() +
coord_cartesian(xlim = c(min(ts_increment_long$Date), max(ts_increment_long$Date)+7), clip = 'off') +
theme(legend.position = c(0.1, 0.8), axis.title.x = element_blank()) +
guides(size = FALSE) +
geom_point(aes(size = Increment), alpha = 0.7) +
scale_size(range = c(2, 10)) +
transition_reveal(Date) +
labs(title = 'World COVID-19 Case Increment at Date: {frame_along}')
anim_save("image/animate_world_increment.gif", animation = animate(animate_world_increment, nframes = 150, fps = 10,renderer = gifski_renderer(loop = FALSE)))
```

Australia
=======================================================================
Column {data-width=400 .bg-secondary}
-----------------------------------------------------------------------
```{r aus_recent_sum}
ts_aus <- ts_all %>%
filter(`Country/Region` == "Australia") %>%
rename(State = `Province/State`,
Country = `Country/Region`) %>%
mutate('New Case' = Confirmed - lag(Confirmed, 1))
aus_recent_sum <- ts_aus %>%
filter(Date == max(Date)) %>%
group_by(Country) %>%
summarise(Date = max(Date),
Confirmed = sum(Confirmed),
'New Case' = sum(`New Case`),
Recovered = sum(Recovered),
Deaths = sum(Deaths))
state_recent <- ts_aus %>%
filter(Date == max(Date))
```
### `r paste0("AUS Confirmed Cases at ", aus_recent_sum$Date)`
```{r aus_confirmed}
valueBox(prettyNum(aus_recent_sum$Confirmed, big.mark = ","), icon = "fa-users", color = "#C70039")
```
### `r paste0("New AUS Cases at ", aus_recent_sum$Date)`
```{r aus_new}
valueBox(prettyNum(aus_recent_sum$`New Case`, big.mark = ","), icon = "fa-users", color = "#fc6b03")
```
### `r paste0("AUS Recovered Cases at ", aus_recent_sum$Date)`
```{r aus_recovered}
valueBox(prettyNum(aus_recent_sum$Recovered, big.mark = ","), icon = "ion-checkmark-circled", color = '#3FBF7F')
```
### `r paste0("AUS Deaths Cases at ", aus_recent_sum$Date)`
```{r aus_deaths}
valueBox(prettyNum(aus_recent_sum$Deaths, big.mark = ","), icon = "ion-close-circled", color = '#d3d3d3')
```
```{r aus_first_case_day}
aus_nz <- ts_aus %>% filter(Confirmed>0)
aus_first_case_day <- min(aus_nz$Date)
```
### `r paste0("Days since First AUS Confirmed Case at ", aus_first_case_day)`
```{r aus_pass_day}
current <- Sys.Date()
aus_pass_day <- current - aus_first_case_day
valueBox(prettyNum(aus_pass_day, big.mark = ","), icon = "ion-android-time", color = '#FFC300')
```
```{r ts_aus_nz}
state_code <- tibble(
"name" = c("Australian Capital Territory", "New South Wales", "Northern Territory", "Queensland", "South Australia","Tasmania", "Victoria","Western Australia"),
"State" = as.factor(c("ACT", "NSW", "NT", "QLD", "SA", "TAS", "VIC", "WA")))
# filter by the first confirmed case appeareds
ts_aus_nz <- ts_aus %>%
rename(name = State) %>%
filter(Confirmed > 0) %>%
left_join(state_code)
```
Column {data-width=600 .tabset}
-----------------------------------------------------------------------
### Animation of AUS COVID-19 Case Increment by Day
```{r ts_increment_aus}
ts_increment_aus_long <- ts_aus_nz %>%
select(Date, Confirmed, Recovered, Deaths, State) %>%
group_by(State) %>%
mutate(Confirmed = Confirmed - lag(Confirmed,1),
Deaths = Deaths - lag(Deaths,1),
Recovered = Recovered - lag(Recovered,1)) %>%
filter(Date != min(Date)) %>%
ungroup() %>%
group_by(Date) %>%
summarise(Confirmed = sum(Confirmed),
Recovered = sum(Recovered),
Deaths = sum(Deaths)) %>%
pivot_longer(-Date, names_to = "Case", values_to = "Increment")
```
```{r animate_aus_increment}
animate_aus_increment <-
ggplot(data = ts_increment_aus_long,
mapping = aes(x = Date, y = Increment, group = Case, color = Case)) +
geom_line() +
scale_color_brewer(palette = "Set3") +
geom_segment(aes(xend = max(Date)+1, yend = Increment), linetype = 2, colour = 'grey') +
geom_text(aes(x = max(Date)+1, label = Case), hjust = 0) +
theme_blog() +
coord_cartesian(xlim = c(min(ts_increment_aus_long$Date), max(ts_increment_aus_long$Date)+7), clip = 'off') +
theme(legend.position = c(0.1, 0.8), axis.title.x = element_blank()) +
guides(size = FALSE) +
geom_point(aes(size = Increment), alpha = 0.7) +
scale_size(range = c(2, 10)) +
transition_reveal(Date) +
labs(title = 'AUS COVID-19 Case Increment at Date: {frame_along}')
anim_save("image/animate_aus_increment.gif", animation = animate(animate_aus_increment, nframes = 100, fps = 10, renderer = gifski_renderer(loop = FALSE)))
```

### Search by State
```{r table_state}
state_recent %>%
select(Country, State, Date, Confirmed, `New Case`, Recovered, Deaths) %>%
arrange(desc(Confirmed)) %>%
datatable(
rownames = FALSE,
fillContainer = TRUE,
options = list(
bPaginate = FALSE)
)
```
State
=======================================================================
Column {data-width=500 .tabset}
-----------------------------------------------------------------------
```{r write_aus_map, eval=FALSE}
aus_map <- read_rds(gzcon(url("https://biogeo.ucdavis.edu/data/gadm3.6/Rsf/gadm36_AUS_1_sf.rds"))) %>%
ms_simplify(keep = 0.01, keep_shapes = TRUE) %>%
fortify_sfc() %>%
filter(NAME_1 != "Ashmore and Cartier Islands" &
NAME_1 != "Coral Sea Islands Territory" &
NAME_1 != "Jervis Bay Territory") %>%
select(NAME_1, polygon, long, lat) %>%
rename(State = NAME_1)
write_csv(aus_map, "data/aus_map.csv")
```
```{r aus_map_recent}
aus_map <- read_csv("data/aus_map.csv",
col_types = cols(
State = col_character(),
polygon = col_double(),
long = col_double(),
lat = col_double()
))
aus_map_recent <- aus_map %>%
left_join(ts_aus %>% filter(Date == max(Date)), by = "State") %>%
select(-Country)
```
### Map of AUS COVID-19 Confirmed Cases
```{r map_aus_confirmed}
ggplot() +
geom_polygon(data = aus_map_recent,
mapping = aes(x = long, y = lat, group = interaction(State, polygon), fill = Confirmed),
color = "grey") +
geom_text() +
theme_map() +
scale_fill_distiller(palette = "YlOrRd", direction = 1) +
theme(plot.margin = margin(0, 0, 0, 0, "pt"),
panel.background = element_rect(fill = "lightblue"),
legend.position = c(0.26, 0.2),
legend.direction = "horizontal",
legend.background = element_rect(fill = "lightblue")) +
ggtitle(paste0("AUS COVID-19 Confirmed Cases by Sate at ", recent_day)) +
geom_text(data = aus_map_recent,
mapping = aes(x = Long,y = Lat, label = paste(State,":",Confirmed)),
size = 2)
```
### AUS Recovered
```{r map_aus_recovered}
ggplot() +
geom_polygon(data = aus_map_recent,
mapping = aes(x = long, y = lat, group = interaction(State, polygon), fill = Recovered),
color = "grey") +
theme_map() +
scale_fill_distiller(palette = "Greens", direction = 1) +
theme(plot.margin = margin(0, 0, 0, 0, "pt"),
panel.background = element_rect(fill = "lightblue"),
legend.position = c(0.26, 0.2),
legend.direction = "horizontal",
legend.background = element_rect(fill = "lightblue")) +
ggtitle(paste0("AUS COVID-19 Recovered Cases by Sate at ", recent_day)) +
geom_text(data = aus_map_recent,
mapping = aes(x = Long,y = Lat, label = paste(State,":",Recovered)),
size = 2)
```
### AUS Deaths
```{r map_aus_deaths}
ggplot() +
geom_polygon(data = aus_map_recent,
mapping = aes(x = long, y = lat, group = interaction(State, polygon), fill = Deaths),
color = "grey") +
theme_map() +
scale_fill_distiller(palette = "Purples", direction = 1) +
theme(plot.margin = margin(0, 0, 0, 0, "pt"),
panel.background = element_rect(fill = "lightblue"),
legend.position = c(0.26, 0.2),
legend.direction = "horizontal",
legend.background = element_rect(fill = "lightblue")) +
ggtitle(paste0("AUS COVID-19 Deaths Cases by Sate at ", recent_day)) +
geom_text(data = aus_map_recent,
mapping = aes(x = Long,y = Lat, label = paste(State,":",Deaths)),
size = 2)
```
Column {data-width=500 .tabset}
-----------------------------------------------------------------------
### Animation of AUS COVID-19 Confirmed Cases
```{r animate_confirmed}
animate_confirmed <-
ggplot(data = ts_aus_nz,
mapping = aes(x = Date, y = Confirmed, group = State, color = State)) +
geom_line() +
scale_color_brewer(palette = "Set3") +
scale_y_log10() +
geom_segment(aes(xend = max(Date)+1, yend = Confirmed), linetype = 2, colour = 'grey') +
geom_text(aes(x = max(Date)+1, label = State), hjust = 0) +
theme_blog() +
coord_cartesian(clip = 'off') +
theme(legend.position = c(0.1, 0.7), axis.title.x = element_blank()) +
guides(size = FALSE) +
geom_point(aes(size = Confirmed), alpha = 0.7) +
scale_size(range = c(2, 10)) +
transition_reveal(Date) +
labs(title = 'AUS COVID-19 Confirmed Cases at Date: {frame_along}')
anim_save("image/animate_confirmed.gif", animation = animate(animate_confirmed, nframes = 120, fps = 10, renderer = gifski_renderer(loop = FALSE)))
```

### AUS Recovered
```{r animate_recovered}
ts_aus_nz_recovered <- ts_aus_nz %>%
filter(Recovered > 0)
animate_recovered <-
ggplot(data = ts_aus_nz_recovered,
mapping = aes(x = Date, y = Recovered, group = State, color = State)) +
geom_line() +
scale_color_brewer(palette = "Set3") +
scale_y_log10() +
geom_segment(aes(xend = max(Date)+1, yend = Recovered), linetype = 2, colour = 'grey') +
geom_text(aes(x = max(Date)+1, label = State), hjust = 0) +
theme_blog() +
coord_cartesian(clip = 'off') +
theme(legend.position = c(0.1, 0.7), axis.title.x = element_blank()) +
guides(size = FALSE) +
geom_point(aes(size = Recovered), alpha = 0.7) +
scale_size(range = c(2, 10)) +
transition_reveal(Date) +
labs(title = 'AUS COVID-19 Recovered Cases at Date: {frame_along}')
anim_save("image/animate_recovered.gif", animation = animate(animate_recovered, nframes = 120, fps = 10, renderer = gifski_renderer(loop = FALSE)))
```

### AUS Deaths
```{r animate_deaths}
ts_aus_nz_deaths <- ts_aus_nz %>%
filter(Deaths > 0)
animate_deaths <-
ggplot(data = ts_aus_nz_deaths,
mapping = aes(x = Date, y = Deaths, group = State, color = State)) +
geom_line() +
scale_color_brewer(palette = "Set3") +
geom_segment(aes(xend = max(Date)+1, yend = Deaths), linetype = 2, colour = 'grey') +
geom_text(aes(x = max(Date)+1, label = State), hjust = 0) +
theme_blog() +
coord_cartesian(clip = 'off') +
theme(legend.position = c(0.1, 0.7), axis.title.x = element_blank()) +
guides(size = FALSE) +
geom_point(aes(size = Deaths), alpha = 0.7) +
scale_size(range = c(2, 10)) +
transition_reveal(Date) +
labs(title = 'AUS COVID-19 Deaths Cases at Date: {frame_along}')
anim_save("image/animate_deaths.gif", animation = animate(animate_deaths, nframes = 120, fps = 10, renderer = gifski_renderer(loop = FALSE)))
```

Sources
=======================================================================
1.The COVID-19 data is from John Hopkins University, https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_time_series.
2.The Australia map data if from GADM, https://gadm.org/data.html
3.The country code is from plotly dataset, https://github.com/plotly/datasets/blob/master/2014_world_gdp_with_codes.csv